<?php
namespace Orx\Mailer\MailBox;
/**
 * Message Object.
 *
 * It represant a message exchange with a contact of Hive
 *
 * @author Xavier VILAIN
 * @package Hive
 * @property int 		$messageid	 			Unique Message id
 * @property int		$idusr					Id of the user who handle the message
 * @property string	 	$boxid					Id of the box which handle the message
 * @property int 		$status	 				Status
 * @property string 	$externalid				External Id
 * @property datetime 	$receive_date			Received Date/Emission Date
 * @property string 	$email_from				Email From
 * @property string 	$email_from_name 		Email From Full Name if there is one
 * @property string 	$reference				Reference Inlineid
 * @property string 	$reference_classname 	Reference Classname 
 * @property string 	$subject				Email Subject
 * @property string 	$content				Content
 * @property string 	$content_html			Full Html Content
 *  
 * @method array attachements()
 * @method \Orx\User\MailBox mailbox()
 */
class Message extends \Fox\Object\Versioned {
	
	/**
	 * Link to receivers
	 * @var string
	 */
	const LINK_RECEIVERS = 'receivers';
		
	/**
	 * Link to email attachements
	 * @var string
	 */
	const LINK_ATTACHEMENTS = 'attachements';
		
	/**
	 * Link to carbon copy
	 * @var string
	 */
	const LINK_CARBON_COPY = 'carbonCopies';
		
	/**
	 * Link to mailbox
	 * @var string
	 */
	const LINK_MAILBOX = 'mailbox';
	
	/**
	 * Link to messages labels
	 */
	const LINK_LABELS = 'labels';
	
	/**
	 * Status Message new
	 * @var int
	 */
	const STATUS_UNREAD = 1;
	
	/**
	 * Status Message has been read
	 * @var int
	 */
	const STATUS_READ = 2;
	
	/**
	 * Draf
	 * @var int
	 */
	const STATUS_DRAFT = 4;
	
	/**
	 * Sent Message
	 * @var int
	 */
	const STATUS_SENT = 3;
	
	/**
	 * Archived Message
	 * @var string
	 */
	const STATUS_ARCHIVED = 5;
	
	/**
	 * Status Deleted
	 * @var int
	 */
	const STATUS_DELETED = 8;
	
	/**
	 * Status On Error
	 * @var int
	 */
	const STATUS_ERROR = 9;	
	
	/**
	 * Status Removed From the application
	 * @var int
	 */
	const STATUS_REMOVED = 99;
		
	/**
	 * When Message Labels are added 
	 */
	const CHANGE_MOVETO = 'moveto';
		
	/**
	 * When Message Labels are added 
	 */
	const CHANGE_DELETE_BOX = 'moveto-delete';
		
	/**
	 * Change Archive 
	 */
	const CHANGE_ARCHIVE = 'archive';
			
	/**
	 * When Message are associate to a contact 
	 */
	const CHANGE_PARSE_CONTACT = 'parse-contact';
			
	/**
	 * When Sending the email
	 */
	const CHANGE_SENDING = 'msg-send';

	/**
	 * Mailbox Reference
	 * @var int
	 */
	const MAILBOX_REFERENCE = 99;
	
	/**
	 * 
	 * Check if this email was not already uploaded
	 * @param string $messagid
	 * @param int $idusr
	 * @param int $boxid
	 */
	public static function isUnique($externalid,$idusr,$boxid) {
		
		$query = \Fox\Dao::infos(self::className())->handle()->createQueryBuilder();
		$query->select('messageid')
			->from('messages','t');
		$fragment = new \Fox\Dao\SqlFragment('idusr = ? AND boxid = ? AND externalid = ?',
						array($idusr,$boxid,$externalid));
		$res =  $fragment->pushIn($query)->execute()->fetchColumn();
		if($res > 0) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * Find Message Parent
	 * @return Message
	 */
	public function parentMessage() {
		$parentid = $this->parentid;
		if(empty($parentid)) {
			return null;
		}
		$parent = \Fox\Dao::finder(self::className())
			->where('messageid = ?',array($this->parentid))
			->find();
		if(count($parent) == 1) {
			return $parent[0];
		} else {
			return null;
		}
	}
	
	/**
	 * Email Content
	 * @return string
	 */
	public function content() {
		$html = $this->content_html;
		if(!empty($html)) {
			return $html;
		} else {
			return $this->content;
		}
	}
	
	/**
	 * (non-PHPdoc)
	 * @see Fox\Object.Versioned::afterVersionUpdate()
	 */
	public function afterVersionUpdate() {
		if($this->isChangeType(self::CHANGE_PARSE_CONTACT)) {
			$searchEngine = new \Fox\SearchEngine();
			$searchEngine->add($this,$this->reference,\Hive\Ressource::className());
		}
	}
	
	/**
	 * 
	 * Formatted data for form initialization
	 * @return array
	 */
	public function getFullFormatedData() {
		$data = $this->getData();
		$data['sender'] = $this->email;
		$data['answerid'] = $this->getId();
		// Receivers
		foreach($this->receivers() as $receiver) {
			$name = $receiver->name;
			if(empty($name)) {
				$name = $receiver->email;
			}
			$data['receivers'][] = array('id' => $receiver->email.':'.$receiver->reference,
												 'ref' => $receiver->reference,
												 'ref_c' => $receiver->reference_class_id,
												 'name' => $name);
		}
		// Carbon Copies
		foreach($this->carbonCopies() as $receiver) {
			$name = $receiver->name;
			if(empty($name)) {
				$name = $receiver->email;
			}
			
			if($receiver->private == 1)  {
				$data['receivers_cci'][] = array('id' => $receiver->email.':'.$receiver->reference,
												 'ref' => $receiver->reference,
												 'ref_c' => $receiver->reference_class_id,
												 'name' => $name);
			} else {
				$data['receivers_ccs'][] = array('id' => $receiver->email.':'.$receiver->reference,
												 'ref' => $receiver->reference,
												 'ref_c' => $receiver->reference_class_id,
												 'name' => $name);
			}
		}
		return $data;
	}
	
	/**
	 * Send the message using Mailbox STMP protocole if available
	 * 
	 * @return bool
	 */
	public function send() {
		// Set STMP Configuration
		$transport = $this->mailbox()->smtp();
		
		$mail = new \Zend_Mail(_CHARSET_);
		// List of recipients
		foreach($this->receivers() as $receiver) {
			$mail->addTo($receiver->email);
		}
		foreach($this->carbonCopies() as $ccs) {
			if($ccs->private == true)  {
				$mail->addCc($ccs->email);
			} else {
				$mail->addCc($ccs->email);
			}
		}
		// Add Thread Header 
		$threadIndex = $this->thread_index;
		if(!empty($threadIndex)) {
			$mail->addHeader('X-Hive-Thread-Index',$threadIndex);
			$mail->addHeader('thread-index',$threadIndex);
		}
		$mail->addHeader('x-hive-message-id',$this->messageid);
		$mail->setSubject($this->subject);
		$content = $this->content();
		$content .= '<p style="height:0;line-height:0;overflow:hidden;color:#FFFFFF;display:none">###'.$this->messageid.'###</p>';
		if(substr($content,0,6) == '<html>') {
			$mail->setBodyHtml($content);
		} else {
			$mail->setBodyHtml("<html><body>$content</body></html>");
		}
		// Mailbox data ?
		$mail->setFrom($this->email,$this->name);
		// Attachement ?
		$attached = false;
		//$attached = $this->getAttached();
		if($attached)
		{
			foreach ($attached as $attach)
			{
				$at = new \Zend_Mime_Part(file_get_contents($attach['file']));
				$at->type        = $attach['type'];
				$at->disposition = \Zend_Mime::DISPOSITION_INLINE;
				$at->encoding    = \Zend_Mime::ENCODING_BASE64;
				$at->filename    = basename($attach['file']);
				$mail->addAttachment($at);
			}
		}
		$this->received_date = \Fox\Object::sqlDateTime(time());
		try {
			$mail->send($transport);// Send mail
			$this->status = self::STATUS_SENT;
		} catch (\Exception $e){
			$this->status = self::STATUS_ERROR;
			$this->error_message = $e->getMessage();
			\Fox\Message::Error($e->getMessage());
		}
		$this->prepareUpdate($this::CHANGE_SENDING);
		$this->update();
	}
	
	/**
	 * Find message children if there is one
	 * @return Message
	 */
	public function childrens() {
		$childrens = \Fox\Dao::finder(self::className())
			->where('parentid = ?',array($this->messageid))
			->find();
		if(count($childrens) > 0) {
			return $childrens;
		} else {
			return array();
		}
	}
	/**
	 * Build Children tree
	 * @return array of Message
	 */
	public static function buildChildrenArray($message) {

		$html[$message->messageid] = $message;
		foreach($message->childrens() as $children) {
			$parts = self::buildChildrenArray($children);
			if(is_array($parts)) {
				$html = array_merge($html,$parts);
			}
		}
		return $html;
	}
	
	/**
	 * 
	 * Find the oldest parent message, it will always be display at the first 
	 * line.
	 * @return Message
	 */
	public static function findTopParent($message) {
		$parent = $message->parentMessage();
		if(!empty($parent)) {
			return self::findTopParent($parent);
		} else {
			return $message;
		}
	}
	
	/**
	 * Find Message Id Key inside message content (should be 
	 * in the html editor has a number between ### )
	 * 
	 * @return int
	 */
	public static function parseContentForMessageId($content) {
		if(preg_match('/###[0-9]*###/',$content,$match)) {
			$parentid = str_replace('#','',$match[0]);
			return $parentid;
		}
		return null;
	}
	
	/**
	 * Extract the content of the answer, and not the conversation
	 * history if it's a reply message, else use the content of the message
	 * 
	 * @param string $content
	 * @return string
	 */
	public static function answerContent($content) {
		// Case of GMAIL messages
		$gmailPosition = strpos($content, '<div class="gmail_quote');
		$hivePosition = strpos($content, '<blockquote');
		if($gmailPosition !== false || $hivePosition !== false)  {
			
			if($hivePosition === false || $hivePosition > $gmailPosition) {
				$content = str_replace('<div class="gmail_quote','#__#__#<div class="gmail_quote',$content);
			} else {
				$content = str_replace('<blockquote','#__#__#<blockquote',$content);
			} 
			
		} else {
			return strip_tags($content);
		}
		// Remove Tags
		$content = strip_tags($content);
		return substr($content,0,strpos($content,'#__#__#'));
	}
	
	/**
	 * 
	 * Extract Summary and format it
	 * @return string
	 */
	public static function summary($content) {
		
		$content = str_replace(array('<br>','<br/>','<br />','\n'),' ',$content);
		$content = self::answerContent($content);
		$content =  \Fox\Utilities\Text::reduce($content,100,'...');
		//$content = \Fox\Utilities\Text::abstractHTMLContents($content,60,'...');
		$content = \Fox\Utilities\Text::closeTags($content);
		$content = \Fox\Utilities\Text::removeHtml($content);
		return trim($content);
	}
	
	/**
	 * Return or build a thead unique index to follow a conversation
	 * @param bool $generateIfEmpty
	 * @return string
	 */
	public function threadIndex($generateIfEmpty = false) {
		$thread_index = $this->thread_index;
		if(empty($thread_index) && $generateIfEmpty) {
			$thread_index = \Fox\Utilities::buildRandomKey(20);
		}
		return $thread_index;
	}
} 
\Fox\Dao::infos(Message::className(),new \Fox\Object\Info('messages', \Fox\Databases::DB_APP));

// Link To Receivers
\Fox\Object\Links::add(\Fox\Dao::link(Message\Receiver::className(),Message\Receiver::LINK_MESSAGE)
	->to(Message::className(), Message::LINK_RECEIVERS)
	->on('messageid')
	->orderBy('email')
	->versionFrom()
);
// Link To Attachements
\Fox\Object\Links::add(\Fox\Dao::link(Message\Attachement::className(),Message\Attachement::LINK_MESSAGE)
	->to(Message::className(), Message::LINK_ATTACHEMENTS)
	->on('messageid')
	->orderBy('filename')
	->versionFrom()
);
// Link To Carbon Copy
\Fox\Object\Links::add(\Fox\Dao::link(Message\CarbonCopy::className(),Message\CarbonCopy::LINK_MESSAGE)
	->to(Message::className(), Message::LINK_CARBON_COPY)
	->on('messageid')
	->orderBy('email')
	->versionFrom()
);

// Link To Mailbox
\Fox\Object\Links::add(\Fox\Dao::link(Message::className(), Message::LINK_MAILBOX)
	->to(\Orx\User\MailBox::className(),\Orx\User\MailBox::LINK_MESSAGES)
	->on('idusr','boxid')
);

// Link To Labels
\Fox\Object\Links::add(\Fox\Dao::link(Message\Label::className(),Message\Label::LINK_MESSAGE)
	->to(Message::className(), Message::LINK_LABELS)
	->on('messageid')
	->versionFrom()
);
